package com.knife.oauth.app.service.impl;

import com.knife.common.exception.CommonException;
import com.knife.oauth.app.service.LoginService;
import com.knife.oauth.constants.KnifeOauthConstant;
import com.knife.oauth.domain.entity.IamUser;
import com.knife.oauth.domain.entity.KnifeUserDetails;
import com.knife.oauth.infra.cache.v2.KnifeIamUserRedisCache;
import com.knife.oauth.infra.mapper.IamUserMapper;
import com.knife.oauth.util.DetailHelper;
import com.knife.oauth.util.ServerRequestUtils;
import com.knife.redis.KnifeRedisHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author tianhao.luo@hand-china.com
 * @version 1.0
 * @date 2022年04月16日 星期六 5:57 下午
 * @description
 * @since 1.0
 */
@Service
public class LoginServiceImpl implements LoginService, KnifeOauthConstant {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtEncoder jwtEncoder;

    @Autowired
    private KnifeRedisHelper knifeRedisHelper;

    @Autowired
    private KnifeIamUserRedisCache knifeIamUserRedisCache;
    @Resource
    private IamUserMapper iamUserMapper;

    @Override
    public String login(IamUser iamUser) {
        knifeRedisHelper.setCurrentDatabase(REDIS_DB);
        try {
            // 使用AuthenticationManager 进行用认证
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(iamUser.getLoginName(), iamUser.getHashPassword());
            Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
            if (Objects.isNull(authenticate)) {
                throw new CommonException("登录失败");
            }
            KnifeUserDetails userDetails = (KnifeUserDetails) authenticate.getPrincipal();
            Jwt jwt = jwtEncoder.encode(JwtEncoderParameters.from(JwtClaimsSet.builder()
                    .claim("userId", userDetails.getUserId())
                    .build()));
            // 将jwt token 和 userId绑定
            knifeRedisHelper.strSet(tokenKey(jwt.getTokenValue()), userDetails.getUserId().toString(), 480, TimeUnit.MINUTES);
            return jwt.getTokenValue();
        } catch (BadCredentialsException e) {
            e.printStackTrace();
            throw new CommonException("密码错误");
        } finally {
            knifeRedisHelper.clearCurrentDatabase();
        }
    }

    @Override
    public IamUser selectUserInfo() {
        return iamUserMapper.selectById(DetailHelper.getUserDetails().getUserId());
    }

    @Override
    public void loginOut(HttpServletRequest httpServletRequest) {
        knifeRedisHelper.setCurrentDatabase(REDIS_DB);
        try {
            String token = ServerRequestUtils.parseToken(httpServletRequest);
            knifeRedisHelper.delKey(tokenKey(token));
        } finally {
            knifeRedisHelper.clearCurrentDatabase();
        }
    }
}
